//
//  main.js
//
//  A project template for using arbor.js
//

(function($){

  var Renderer = function(canvas){
    var canvas = $(canvas).get(0)
    var ctx = canvas.getContext("2d");
    var gfx = arbor.Graphics(canvas)
    var particleSystem

    var that = {
      init:function(system){
        //
        // the particle system will call the init function once, right before the
        // first frame is to be drawn. it's a good place to set up the canvas and
        // to pass the canvas size to the particle system
        //
        // save a reference to the particle system for use in the .redraw() loop
        particleSystem = system

        // inform the system of the screen dimensions so it can map coords for us.
        // if the canvas is ever resized, screenSize should be called again with
        // the new dimensions
        particleSystem.screenSize(canvas.width, canvas.height) 
        particleSystem.screenPadding(80) // leave an extra 80px of whitespace per side
        
        // set up some event handlers to allow for node-dragging
        that.initMouseHandling()
      },
      
      redraw:function(){
        // 
        // redraw will be called repeatedly during the run whenever the node positions
        // change. the new positions for the nodes can be accessed by looking at the
        // .p attribute of a given node. however the p.x & p.y values are in the coordinates
        // of the particle system rather than the screen. you can either map them to
        // the screen yourself, or use the convenience iterators .eachNode (and .eachEdge)
        // which allow you to step through the actual node objects but also pass an
        // x,y point in the screen's coordinate system
        // 
        //ctx.fillStyle = "white"
        //ctx.fillRect(0,0, canvas.width, canvas.height)

        gfx.clear()
        
        particleSystem.eachEdge(function(edge, pt1, pt2){
          gfx.line(pt1, pt2, {stroke:"#b2b19d", width:2})
        })
        particleSystem.eachNode(function(node, pt){
          var w = node.data.width || Math.max(20, 20+gfx.textWidth(node.name) )
          if (node.data.alpha===0) return
          ctx.fillStyle = (node.data.alone) ? "orange" : "black"
          var alpha = node.data.alpha || 1;
          var size = 12;
          if(node.data.style)
            size |= node.data.style.size;
          var tcol = node.data.textcolor || "white";
          if (node.data.shape=='dot'){
            var col = node.data.color||"#b2b19d"
            gfx.oval(pt.x-w/2, pt.y-w/2, w, w, {fill:col, alpha:alpha})
            gfx.text(node.name, pt.x, pt.y+size*0.6, {color:tcol, align:"center", font:"Arial", size:size})
            gfx.text(node.name, pt.x, pt.y+size*0.6, {color:tcol, align:"center", font:"Arial", size:size})
          }else{
            var col = node.data.color||"#a7af00"
            gfx.rect(pt.x-w/2, pt.y-8, w, 20, 4, {fill:col, alpha:alpha})
            gfx.text(node.name, pt.x, pt.y+9, {color:tcol, align:"center", font:"Arial", size:size})
            gfx.text(node.name, pt.x, pt.y+9, {color:tcol, align:"center", font:"Arial", size:size})
          }
        })

      /*  particleSystem.eachNode(function(node, pt){
          // node: {mass:#, p:{x,y}, name:"", data:{}}
          // pt:   {x:#, y:#}  node position in screen coords

          // draw a rectangle centered at pt
          var w = 10
          ctx.fillStyle = (node.data.alone) ? "orange" : "black"
          ctx.fillRect(pt.x-w/2, pt.y-w/2, w,w)
        })   */ 			
      },
      
      initMouseHandling:function(){
        // no-nonsense drag and drop (thanks springy.js)
        var dragged = null;

        // set up a handler object that will initially listen for mousedowns then
        // for moves and mouseups while dragging
        var handler = {
          clicked:function(e){
            var pos = $(canvas).offset();
            _mouseP = arbor.Point(e.pageX-pos.left, e.pageY-pos.top)
            dragged = particleSystem.nearest(_mouseP);

            if (dragged && dragged.node !== null){
              // while we're dragging, don't let physics move the node
              dragged.node.fixed = true
              if(dragged.node.data.links){
                for(var i=0; i<dragged.node.data.links.length; i++){
                  sys.addEdge(dragged.node,dragged.node.data.links[i])
                }
                dragged.node.data.links = false;
                dragged.node.data.color='orange';
              }
            }

            $(canvas).bind('mousemove', handler.dragged)
            $(window).bind('mouseup', handler.dropped)

            return false
          },
          dragged:function(e){
            var pos = $(canvas).offset();
            var s = arbor.Point(e.pageX-pos.left, e.pageY-pos.top)

            if (dragged && dragged.node !== null){
              var p = particleSystem.fromScreen(s)
              dragged.node.p = p
            }

            return false
          },

          dropped:function(e){
            if (dragged===null || dragged.node===undefined) return
            if (dragged.node !== null) dragged.node.fixed = false
            dragged.node.tempMass = 1000
            dragged = null
            $(canvas).unbind('mousemove', handler.dragged)
            $(window).unbind('mouseup', handler.dropped)
            _mouseP = null
            return false
          }
        }
        
        // start listening
        $(canvas).mousedown(handler.clicked);

      },
      
    }
    return that
  }    

  $(document).ready(function(){

    var uow = Math.abs(window.innerWidth-window.innerHeight);
    var width_log = 300;
    $('#div_panel').width(width_log).height(window.innerHeight);
    $('#viewport').width(window.innerWidth-width_log).height(window.innerHeight);
    var c = $("#viewport"), 
    ctx = c[0].getContext('2d');
    ctx.canvas.width = window.innerWidth-width_log;
    ctx.canvas.height = window.innerHeight;

    ConsoleLogHTML.connect(document.getElementById("myULContainer")); // Redirect log messages
    console.log("Events start...");

    sys = arbor.ParticleSystem() // create the system with sensible repulsion/stiffness/friction
    sys.parameters({gravity:true}) // use center-gravity to make the graph settle nicely (ymmv)
    //sys.parameters({stiffness:900, repulsion:2000, gravity:true, dt:0.015})
    sys.renderer = Renderer("#viewport") // our newly created renderer will have its .init() method called shortly by sys...

    //实际使用中，（2011年11月时）发现有个bug，就是如果只构造一个节点，就会陷入死循环，所以要避免
    sys.addNode('连', {shape:"dot",textcolor:'#66ccff',color:'#f5f5dc',style:{size:50},width:100})

    var events=[
      ['【丐帮】出现','D','丐帮'],
      ['【王重阳】出生','N','王重阳'],
      ['【洪七公】出生','N','洪七公'],
      ['【黄药师】出生','N','黄药师'],
      ['【周伯通】出生','N','周伯通'],
      ['【王重阳】创立【全真教】','G',['D','全真教','E','王重阳','全真教']],
      ['【周伯通】加入【全真教】','E','周伯通','全真教'],
      ['【洪七公】执掌【丐帮】','E','洪七公','丐帮'],
      ['【黄药师】成为【桃花岛】岛主','G',['D','桃花岛','E','黄药师','桃花岛']],
      ['【王重阳】、【洪七公】、【黄药师】 参与华山论剑，获得【天下五绝】称号',
        'G',['D','天下五绝','E','王重阳','天下五绝','E','洪七公','天下五绝','E','黄药师','天下五绝']],
      ['【丘处机】出生','N','丘处机'],
      ['【丘处机】加入【全真教】','E','丘处机','全真教'],
      ['【郭靖】出生','N','郭靖'],
      ['【黄蓉】出生并定居【桃花岛】','G',['N','黄蓉','E','黄蓉','黄药师','E','黄蓉','桃花岛']],
      ['【丘处机】传授【郭靖】武艺','E','丘处机','郭靖'],
      ['【郭靖】和【黄蓉】定情','E','郭靖','黄蓉'],
      ['【洪七公】收【郭靖】、【黄蓉】为徒','G',['E','洪七公','郭靖','E','洪七公','黄蓉']],
      ['【郭靖】和【周伯通】结拜兄弟','E','郭靖','周伯通'],
      ['【黄蓉】执掌【丐帮】','E','黄蓉','丐帮'],
    ]

      
    var drawEvent = function(evt,pos){
      switch(evt[pos]){
        case 'D':
          pos++;
          sys.addNode(evt[pos],{shape:"dot",color:'orange'});
          break;
        case 'N':
          pos++
          sys.addNode(evt[pos]);
          break;
        case 'E':
          sys.addEdge(evt[pos+1],evt[pos+2]);
          pos+=2;
          break;
        case 'G':
          var p1 = 0;
          var gevt = evt[pos+1];
          while(p1<gevt.length-2){
            p1 = drawEvent(gevt,p1);
          }            
          break;
      }
      return pos+1;
    }

    var epos = 0;
    var step = function(){
      var evt = events[epos];
      console.log(evt[0]);
      drawEvent(evt,1);
      epos++;
      if(epos<events.length){
        setTimeout(step,500);
      }else{
        setTimeout(function(){
          console.log('【连琪】创立');
          sys.addNode('琪', {shape:"dot",textcolor:'#66ccff',color:'#f5f5dc',style:{size:50},width:100})
          sys.addEdge('连','琪')
          setTimeout(function(){
            sys.addNode('京ICP备17063343号',{textcolor:'#696969'})
            sys.addEdge('连','京ICP备17063343号')
            sys.addEdge('琪','京ICP备17063343号')
          },1000);
        },1000);
      }
    }
    step();
    // or, equivalently:
    //
    // sys.graft({
    //   nodes:{
    //     "f":{alone:true, mass:.25,alpha:1}
    //   }, 
    //   edges:{
    //     "郭靖":{ "黄蓉":{},
    //         "丘处机":{"王重阳":{"周伯通":{"郭靖":{}}}},
    //         d:{},
    //         e:{}
    //     }
    //   }
    // })
    /*
    【王重阳】出生
    【洪七公】出生
    【周伯通】出生
    【王重阳】创立【全真教】
    【洪七公】执掌【丐帮】
    【黄药师】成为【桃花岛】岛主
    【周伯通】加入【全真教】
    【王重阳】、【洪七公】、【黄药师】 参与华山论剑，获得【天下五绝】称号
    【丘处机】出生
    【丘处机】加入【全真教】
    【郭靖】出生
    【黄蓉】出生并定居【桃花岛】
    【丘处机】传授【郭靖】武艺
    【郭靖】和【黄蓉】定情
    【洪七公】收【郭靖】、【黄蓉】为徒
    【郭靖】和【周伯通】结拜兄弟
    【黄蓉】接任【丐帮】帮主

    丐帮的小乞丐 向 全真教的小道士 借一笔钱
    */
    
  })

})(this.jQuery)